package com.xuanwei.schedule.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundQueryRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.xuanwei.dao.entity.XwOrder;
import com.xuanwei.dao.entity.XwOrderPayLog;
import com.xuanwei.dao.entity.XwOrderRefund;
import com.xuanwei.dao.mapper.XwOrderMapper;
import com.xuanwei.dao.mapper.XwOrderPayLogMapper;
import com.xuanwei.dao.mapper.XwOrderRefundMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author jiangyong
 * @Description TODO
 * @Date 2019/7/25 15:44
 **/
@Service
@Slf4j
public class OrderService {

    private XwOrderMapper orderMapper;

    private WxPayService payService;

    private XwOrderPayLogMapper payLogMapper;

    private XwOrderRefundMapper orderRefundMapper;

    public OrderService(XwOrderMapper orderMapper,
                        WxPayService payService,
                        XwOrderPayLogMapper payLogMapper,
                        XwOrderRefundMapper orderRefundMapper) {
        this.orderMapper = orderMapper;
        this.payService = payService;
        this.payLogMapper = payLogMapper;
        this.orderRefundMapper = orderRefundMapper;
    }

    /**
     * 查询未支付订单
     *
     * @param page 分页参数
     * @return 所有ID
     */
    public List<Integer> findCloseOrderIds(Page<XwOrder> page) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime time = now.minusMinutes(30);
        orderMapper.selectPage(page, new QueryWrapper<XwOrder>()
                .select("id")
                .in("`status`", 0, 7)
                .lt("create_time", time)
        );
        return page.getRecords().stream().map(XwOrder::getId).collect(Collectors.toList());
    }

    /**
     * 查询发货订单
     *
     * @param page 分页
     * @return ID集合
     */
    public List<Integer> findSendOrderIds(Page<XwOrder> page) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime time = now.minusDays(10);
        orderMapper.selectPage(page, new QueryWrapper<XwOrder>()
                .select("id")
                .eq("`status`", 2)
                .lt("send_time", time)
        );
        return page.getRecords().stream().map(XwOrder::getId).collect(Collectors.toList());
    }


    /**
     * 查询未评论订单
     *
     * @param page 分页
     * @return ID集合
     */
    public List<Integer> findNoCommentOrderIds(Page<XwOrder> page) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime time = now.minusDays(5);
        orderMapper.selectPage(page, new QueryWrapper<XwOrder>()
                .select("id")
                .eq("`status`", 3)
                .lt("send_time", time)
        );
        return page.getRecords().stream().map(XwOrder::getId).collect(Collectors.toList());
    }

    /**
     * 查询支付
     *
     * @param page
     * @return
     */
    public List<NoPayStatus> findNoPayStatus(Page<XwOrder> page) {

        List<NoPayStatus> result = new ArrayList<>();

        page.getRecords().forEach(s -> {
            String orderNo = s.getOrderNo();
            WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
            request.setOutTradeNo(orderNo);
            try {
                WxPayOrderQueryResult wxPayOrderQueryResult = payService.queryOrder(request);

                String tradeState = wxPayOrderQueryResult.getTradeState();
                insertLog(s.getOrderNo(), tradeState, wxPayOrderQueryResult, 2);
                if ("SUCCESS".equals(tradeState)) {
                    NoPayStatus status = new NoPayStatus();
                    status.setOrderId(s.getId());
                    status.setType(1);
                    result.add(status);

                } else if ("NOTPAY".equals(tradeState)) {
                    NoPayStatus status = new NoPayStatus();
                    status.setOrderId(s.getId());
                    status.setType(2);
                    result.add(status);
                }

            } catch (WxPayException e) {
                e.printStackTrace();
            }
        });
        return result;
    }

    /**
     * 查询退款
     *
     * @param page
     * @return
     */
    public List<Integer> findRefundStatus(Page<XwOrderRefund> page) {

        List<Integer> ids = new ArrayList<>();
        orderRefundMapper.selectPage(page, new QueryWrapper<XwOrderRefund>()
                .select("id,order_id").eq("`status`", 3));

        page.getRecords().forEach(s -> {
            Integer orderId = s.getOrderId();
            XwOrder order = orderMapper.selectOne(new QueryWrapper<XwOrder>()
                    .select("id").eq("id", orderId));
            String orderNo = order.getOrderNo();
            WxPayRefundQueryRequest request = new WxPayRefundQueryRequest();
            request.setOutTradeNo(orderNo);
            try {
                WxPayRefundQueryResult wxPayRefundQueryResult = payService.refundQuery(request);
                //退款设置为全部退款(所以只有一笔)
                List<WxPayRefundQueryResult.RefundRecord> refundRecords = wxPayRefundQueryResult.getRefundRecords();
                String refundStatus = refundRecords.get(0).getRefundStatus();
                if ("SUCCESS".equals(refundStatus)) {
                    ids.add(s.getId());
                }
                insertLog(orderNo, refundStatus, wxPayRefundQueryResult, 4);

            } catch (WxPayException e) {
                e.printStackTrace();
            }
        });
        return ids;
    }

    /**
     * 插入日志
     *
     * @param orderNo
     * @param R
     * @param result
     * @param type
     */
    public void insertLog(String orderNo, String R, BaseWxPayResult result, Integer type) {
        XwOrderPayLog orderPayLog = payLogMapper.selectOne(new QueryWrapper<XwOrderPayLog>().select("id")
                .eq("order_no", orderNo)
                .eq("type", type));
        if (orderPayLog == null) {
            orderPayLog = new XwOrderPayLog();
            orderPayLog.setType(type);
            orderPayLog.setCreateTime(LocalDateTime.now());
            orderPayLog.setErrCodeDes(result.getErrCodeDes());
            orderPayLog.setOrderNo(orderNo);
            orderPayLog.setResultCode(result.getResultCode());
            orderPayLog.setReturnCode(result.getReturnCode());
            orderPayLog.setReturnMsg(result.getReturnMsg());
            orderPayLog.setTypeResult(R);
            payLogMapper.insert(orderPayLog);
        } else {
            orderPayLog.setCreateTime(LocalDateTime.now());
            orderPayLog.setErrCodeDes(result.getErrCodeDes());
            orderPayLog.setResultCode(result.getResultCode());
            orderPayLog.setReturnCode(result.getReturnCode());
            orderPayLog.setReturnMsg(result.getReturnMsg());
            orderPayLog.setTypeResult(R);
            payLogMapper.updateById(orderPayLog);
        }
    }

    public static class NoPayStatus {
        private Integer orderId;

        //1微信返回成功,2微信返回没有该笔订单
        private Integer type;

        public Integer getOrderId() {
            return orderId;
        }

        public void setOrderId(Integer orderId) {
            this.orderId = orderId;
        }

        public Integer getType() {
            return type;
        }

        public void setType(Integer type) {
            this.type = type;
        }
    }
}
